#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<signal.h>
#include<arpa/inet.h>
#include<netdb.h>
#include<sys/wait.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<pthread.h>
#include<sys/stat.h>

void *TransSocketThread(void* );

typedef struct {
   int m_SocketSrc;
   int m_SocketDest;
}T_AddrPort;

char m_Buf[512*1024] = {0}; // 缓冲区--暂存

int m_MainId = 0; // Main ID
int m_ListenSocket = 0; // Listen Socket -- Client
char m_ConnectAddr[256] = {0}; // Server IP
char m_ConnectPort[256] = {0}; // Server Port

/*
 *  1. 生成一个侦听client的套接字
 */
int GetListenSocket(int nPort)
{
     // 本地地址
        struct sockaddr_in m_LisAddr = {0};
        int    m_Socket = 0;
        int    m_AddrLen = sizeof(struct sockaddr_in);

        m_LisAddr.sin_family = AF_INET;
        m_LisAddr.sin_port = htons(nPort);
        m_LisAddr.sin_addr.s_addr = INADDR_ANY;

     // Socket
        if((m_Socket = socket(AF_INET, SOCK_STREAM,0))<0){
               return 0;  // 创建失败
        }
     // bind Socket
        if(bind(m_Socket, (struct sockaddr*)&m_LisAddr, m_AddrLen)<0){
               return 0;  // 绑定失败
        }
     // listen Socket
        if(listen(m_Socket, 5)){
               close(m_Socket); // !important
               return 0;   // 监听失败
        }
        return m_Socket;
}

/*
 *  2. 获取Ftp服务器的Socket -- 这个以后要换成读取地址和端口列表（多个Socket)
 */
int  GetConnectSocket(char* pServerAddr, char* pServerPort)
{
         struct sockaddr_in m_ServerAddr = {0};
         int    m_AddrLen = sizeof(struct sockaddr_in);
         int    m_Socket = 0;
      // 初始化连接信息
         m_ServerAddr.sin_addr.s_addr = inet_addr(pServerAddr);
         m_ServerAddr.sin_port = htons(atoi(pServerPort));
         m_ServerAddr.sin_family = AF_INET;
      // 创建套接字
         m_Socket = socket(AF_INET, SOCK_STREAM, 0);
         if(m_Socket <=0){
               return 0; // 创建失败
         }
      // 连接
         if(connect(m_Socket,(struct sockaddr*)&m_ServerAddr, m_AddrLen)<0){
               close(m_Socket); // !important
               return 0;
         }
         return m_Socket;
}

/*
 *  3. 两个套接字之间的数据暂存与转发--这里就实现了代理的功能
 */
void TransSocket( int m_SendSocket, int m_RecvSocket)
{
        char m_Buf[512*1024] = {0}; // 缓冲区--暂存
        int  ret = 0;

        struct timeval tm = {0};
        tm.tv_sec = 3600*24;

        fd_set  readset;
        FD_ZERO(&readset);
        FD_SET(m_RecvSocket, &readset);
        while(1){
             printf("Data!\n");
             if((select(m_RecvSocket+1, &readset, NULL, NULL, &tm)<=0)){
                   break;
             }
             if(!FD_ISSET(m_RecvSocket,&readset))
                   continue;
             // 从m_RecvSocket,接收数据
             ret = recv(m_RecvSocket, m_Buf, 512*1024-1, 0);
             printf("%s\n",m_Buf);
             if(ret <0){
                   break; // 接受Ftp服务器数据失败
             }
             // 将接收到的数据传给客户端
             send(m_SendSocket, m_Buf,ret,0);
        }
        close(m_SendSocket);
        close(m_RecvSocket);
}

/**
 *   3.1 线程函数
 */
void *TransSocketThread(void* pArgs)
{
        T_AddrPort *pAddrPort = (T_AddrPort*)pArgs;
        int m_SendSocket = pAddrPort->m_SocketSrc;
        int m_RecvSocket = pAddrPort->m_SocketDest;

        int  ret = 0;

        struct timeval tm = {0};
        tm.tv_sec = 3600*24;

        fd_set  readset;
        FD_ZERO(&readset);
        FD_SET(m_RecvSocket, &readset);
        while(1){
             printf("Data!\n");
             if((select(m_RecvSocket+1, &readset, NULL, NULL, &tm)<=0)){
                   break;
             }
             if(!FD_ISSET(m_RecvSocket,&readset))
                   continue;
             // 从m_RecvSocket,接收数据
             ret = recv(m_RecvSocket, m_Buf, 512*1024-1, 0);
             printf("%s\n",m_Buf);
             if(ret <0){
                   break; // 接受Ftp服务器数据失败
             }
             // 将接收到的数据传给客户端
             send(m_SendSocket, m_Buf,ret,0);
        }
        delete pArgs;
}

/*
 *  4. 主逻辑，完成侦听Socket和服务器Socket，并完成他们之间的数据接收和转发
 *     没有接收命令哇
 */
void  SocketTrans()
{
         struct sockaddr_in m_WorkAddr = {0};
         int    m_191Socket = 0;
         int    m_147Socket = 0;
         int    m_WorkAddrLen = 0;

      // 使用得到的侦听socket，获取客户端信息
         while(1){
             // accept -- 侦听端口，客户端Socket
                m_WorkAddrLen = sizeof(struct sockaddr_in);
                m_147Socket = accept(m_ListenSocket,(struct sockaddr*)&m_WorkAddr,(socklen_t*)&m_WorkAddrLen);
                if(m_147Socket<0)
                   continue;
                printf("Cool,Get in!\n");
             // 服务器Ftp的Socket，使用第2个函数
                m_191Socket = GetConnectSocket(m_ConnectAddr, m_ConnectPort);
                if(m_191Socket==0){
                     close(m_147Socket); // !important
                     continue;
                }
             // 开始客户端Socket(m_147Socket)-》服务器Socket(m_191Socket)发送数据（命令）
                TransSocket(m_147Socket,m_191Socket);
                printf("Send--Mission Complete!");
                TransSocket(m_191Socket,m_147Socket);
                printf("Recv-Mission Complete!");
         }
         close(m_191Socket);
         close(m_147Socket);
}

/**
 *  4.1 适合于线程的主函数
 */
 void SocketTransThread()
 {
         struct sockaddr_in m_WorkAddr = {0};
         int    m_191Socket = 0;
         int    m_147Socket = 0;
         int    m_WorkAddrLen = 0;
         m_WorkAddrLen = sizeof(struct sockaddr_in);
         m_147Socket = accept(m_ListenSocket,(struct sockaddr*)&m_WorkAddr,(socklen_t*)&m_WorkAddrLen);
         if(m_147Socket<0)
                return;
         printf("Cool,Get in!\n");
      // 服务器Ftp的Socket，使用第2个函数
         m_191Socket = GetConnectSocket(m_ConnectAddr, m_ConnectPort);
         if(m_191Socket==0){
                close(m_147Socket); // !important
                return;
         }
      // 构造传递的参数
         T_AddrPort *temp1 = new T_AddrPort;
         temp1->m_SocketSrc = m_147Socket;
         temp1->m_SocketDest = m_191Socket;

         T_AddrPort *temp2 = new T_AddrPort;
         temp2->m_SocketSrc = m_191Socket;
         temp2->m_SocketDest = m_147Socket;

         pthread_t pid1,pid2;
         pthread_create(&pid1, NULL, TransSocketThread, (void*)temp1);
         pthread_create(&pid2, NULL, TransSocketThread, (void*)temp2);
      // 阻塞-等待线程结束
         pthread_join(pid2, NULL);
         close(m_147Socket);
         close(m_191Socket);
 }


/*
 *  You Know, Let's Do it!!
 */
int main(int argc, char* argv[])
{
      char* pArgv[] = {
         "",
         "4000",
         "192.168.56.1",
         "21"
       };
       strcpy(m_ConnectAddr, pArgv[2]);
       strcpy(m_ConnectPort, pArgv[3]);
    // listen
       m_ListenSocket = GetListenSocket(atoi(pArgv[1]));
       if(m_ListenSocket == 0){
            printf("Listen [%s] error!\n",pArgv[1]);
            fflush(stdout);
            return 0;
       }
    // start
       SocketTransThread();
       close(m_ListenSocket);
       printf("Hi, man,done!");
       return 0;
}
